﻿"""
MyST-compatible drop-in replacement for Sphinx's Autosummary extension

This extension overrides Autosummary's generation of [domain] roles
(cross-references) so that the syntax is Markdown, just as the MyST parser
expects, and not reStructuredText, as intended for Sphinx's built-in parser.

Note that this is very much a hack. Autosummary should be aware of the document
parser it creates content for, but it's not. That would require substantial
upstream changes.

© 2022 John Hennig, [MIT license]

[domain]: https://www.sphinx-doc.org/en/master/usage/restructuredtext\
/domains.html
[MIT license]: https://www.tldrlegal.com/license/mit-license
"""
__version__ = '0.2.1'


from sphinx.ext import autosummary
from docutils.nodes import Node


class Autosummary(autosummary.Autosummary):
    """Extends the `autosummary` directive provided by Autosummary."""

    def get_table(
        self, items: list[tuple[str, str | None, str, str]]
    ) -> list[Node]:
        """
        Monkey-patches the generation of the summary table.

        All we do here is replace each of the `:py:obj:` strings generated by
        Autosummary with the MyST-style directive `{py:obj}` if MyST is the
        document parser.
        """

        # Find out if parser is MyST.
        # The way we do this is a hack. There must be a better way.
        parser_is_myst = self.state.__module__.startswith('myst')

        # Install our parser hook.
        if parser_is_myst:
            myst_parse = self.state.nested_parse

            def shim(block, offset, node, **arguments):
                block.replace(':py:obj:', '{py:obj}')
                myst_parse(block, offset, node, **arguments)

            self.state.nested_parse = shim

        # Let Autosummary do its thing.
        (table_spec, table) = super().get_table(items)

        # Uninstall our hook so we don't mess with anything else.
        if parser_is_myst:
            self.state.nested_parse = myst_parse

        # Return the Autosummary table.
        return [table_spec, table]


def setup(app):
    """
    Sets up the extension.

    Sphinx calls this function if the user named this extension in `conf.py`.
    We then set up the Autodoc extension that ships with Sphinx and override
    the generation of domain directives.
    """
    app.setup_extension('sphinx.ext.autosummary')
    app.add_directive('autosummary', Autosummary, override=True)
    return {'version': __version__, 'parallel_read_safe': True}
